From: Colin Walters Date: Tue, 24 Jun 2025 20:39:00 +0000 (-0400) Subject: prepare-root: Move /etc handling into library X-Git-Tag: archive/raspbian/2025.7-2+rpi1^2^2~6^2~4^2~17^2 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https://%22%22/%22http:/www.example.com/cgi/%22https:/%22%22?a=commitdiff_plain;h=6243e525f63a58dc6660ad5a5fb88312397f2171;p=ostree.git prepare-root: Move /etc handling into library Prep for soft reboots. Signed-off-by: Colin Walters --- diff --git a/src/libotcore/otcore-prepare-root.c b/src/libotcore/otcore-prepare-root.c index 3efdf576..5add9077 100644 --- a/src/libotcore/otcore-prepare-root.c +++ b/src/libotcore/otcore-prepare-root.c @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef HAVE_COMPOSEFS #include @@ -34,6 +35,8 @@ #define BINDING_KEYPATH "/etc/ostree/initramfs-root-binding.key" // The kernel argument to configure composefs #define CMDLINE_KEY_COMPOSEFS "ostree.prepare-root.composefs" +// The key in the config for etc +#define ETC_KEY "etc" static bool proc_cmdline_has_key_starting_with (const char *cmdline, const char *key) @@ -362,6 +365,63 @@ composefs_error_message (int errsv) #endif +/** + * otcore_mount_etc: + * + * Mount /etc for a deployment, assuming that the current process working directory is the source. + */ +gboolean +otcore_mount_etc (GKeyFile *config, GVariantBuilder *metadata_builder, const char *mount_target, + GError **error) +{ + gboolean etc_transient = FALSE; + if (!ot_keyfile_get_boolean_with_default (config, ETC_KEY, OTCORE_PREPARE_ROOT_TRANSIENT_KEY, + FALSE, &etc_transient, error)) + return glnx_prefix_error (error, "Failed to parse etc.transient value"); + + g_autofree char *target_etc = g_build_filename (mount_target, "etc", NULL); + if (etc_transient) + { + const char *ovldir = "/run/ostree/transient-etc"; + + g_variant_builder_add (metadata_builder, "{sv}", OTCORE_RUN_BOOTED_KEY_TRANSIENT_ETC, + g_variant_new_string (ovldir)); + + // Our lower directory is usr/etc. + g_autofree char *lowerdir = g_build_filename (mount_target, "usr/etc", NULL); + // Standard overlayfs tempdirs + g_autofree char *upperdir = g_build_filename (ovldir, "upper", NULL); + g_autofree char *workdir = g_build_filename (ovldir, "work", NULL); + + struct + { + const char *path; + int mode; + } subdirs[] = { { ovldir, 0700 }, { upperdir, 0755 }, { workdir, 0755 } }; + for (int i = 0; i < G_N_ELEMENTS (subdirs); i++) + { + if (mkdirat (AT_FDCWD, subdirs[i].path, subdirs[i].mode) < 0) + return glnx_throw_errno_prefix (error, "Failed to create dir %s", subdirs[i].path); + } + + g_autofree char *ovl_options + = g_strdup_printf ("lowerdir=%s,upperdir=%s,workdir=%s", lowerdir, upperdir, workdir); + if (mount ("overlay", target_etc, "overlay", MS_SILENT, ovl_options) < 0) + return glnx_throw_errno_prefix (error, "failed to mount transient etc overlayfs"); + } + else + { + /* Bind-mount /etc (at deploy path), and remount as writable. */ + if (mount ("etc", target_etc, NULL, MS_BIND | MS_SILENT, NULL) < 0) + return glnx_throw_errno_prefix (error, "failed to prepare /etc bind-mount at %s", + target_etc); + if (mount (target_etc, target_etc, NULL, MS_BIND | MS_REMOUNT | MS_SILENT, NULL) < 0) + return glnx_throw_errno_prefix (error, "failed to make writable /etc bind-mount at %s", + target_etc); + } + return TRUE; +} + gboolean otcore_mount_rootfs (ComposefsConfig *composefs_config, GVariantBuilder *metadata_builder, gboolean root_transient, const char *root_mountpoint, const char *deploy_path, diff --git a/src/libotcore/otcore.h b/src/libotcore/otcore.h index 378878df..01468b1f 100644 --- a/src/libotcore/otcore.h +++ b/src/libotcore/otcore.h @@ -99,6 +99,9 @@ gboolean otcore_mount_rootfs (ComposefsConfig *composefs_config, GVariantBuilder const char *deploy_path, const char *mount_target, bool *out_using_composefs, GError **error); +gboolean otcore_mount_etc (GKeyFile *config, GVariantBuilder *metadata_builder, + const char *mount_target, GError **error); + // Our directory with transient state (eventually /run/ostree-booted should be a link to // /run/ostree/booted) #define OTCORE_RUN_OSTREE "/run/ostree" @@ -128,6 +131,7 @@ gboolean otcore_mount_rootfs (ComposefsConfig *composefs_config, GVariantBuilder #define OTCORE_PREPARE_ROOT_COMPOSEFS_KEY "composefs" #define OTCORE_PREPARE_ROOT_ENABLED_KEY "enabled" #define OTCORE_PREPARE_ROOT_KEYPATH_KEY "keypath" +#define OTCORE_PREPARE_ROOT_TRANSIENT_KEY "transient" // The file written in the initramfs which contains an a{sv} of metadata // from ostree-prepare-root. diff --git a/src/switchroot/ostree-prepare-root.c b/src/switchroot/ostree-prepare-root.c index 7f350412..8cdfbaa7 100644 --- a/src/switchroot/ostree-prepare-root.c +++ b/src/switchroot/ostree-prepare-root.c @@ -81,8 +81,6 @@ /* This key configures the / mount in the deployment root */ #define ROOT_KEY "root" -#define ETC_KEY "etc" -#define TRANSIENT_KEY "transient" #define OSTREE_PREPARE_ROOT_DEPLOYMENT_MSG \ SD_ID128_MAKE (71, 70, 33, 6a, 73, ba, 46, 01, ba, d3, 1a, f8, 88, aa, 0d, f7) @@ -188,8 +186,8 @@ main (int argc, char *argv[]) gboolean sysroot_readonly = FALSE; gboolean root_transient = FALSE; - if (!ot_keyfile_get_boolean_with_default (config, ROOT_KEY, TRANSIENT_KEY, FALSE, &root_transient, - &error)) + if (!ot_keyfile_get_boolean_with_default (config, ROOT_KEY, OTCORE_PREPARE_ROOT_TRANSIENT_KEY, + FALSE, &root_transient, &error)) return FALSE; // We always parse the composefs config, because we want to detect and error @@ -306,51 +304,8 @@ main (int argc, char *argv[]) * the deployment needs to be created and remounted as read/write. */ if (sysroot_readonly || using_composefs || root_transient) { - gboolean etc_transient = FALSE; - if (!ot_keyfile_get_boolean_with_default (config, ETC_KEY, TRANSIENT_KEY, FALSE, - &etc_transient, &error)) - errx (EXIT_FAILURE, "Failed to parse etc.transient value: %s", error->message); - - static const char *tmp_sysroot_etc = TMP_SYSROOT "/etc"; - if (etc_transient) - { - char *ovldir = "/run/ostree/transient-etc"; - - g_variant_builder_add (&metadata_builder, "{sv}", OTCORE_RUN_BOOTED_KEY_TRANSIENT_ETC, - g_variant_new_string (ovldir)); - - char *lowerdir = "usr/etc"; - if (using_composefs) - lowerdir = TMP_SYSROOT "/usr/etc"; - - g_autofree char *upperdir = g_build_filename (ovldir, "upper", NULL); - g_autofree char *workdir = g_build_filename (ovldir, "work", NULL); - - struct - { - const char *path; - int mode; - } subdirs[] = { { ovldir, 0700 }, { upperdir, 0755 }, { workdir, 0755 } }; - for (int i = 0; i < G_N_ELEMENTS (subdirs); i++) - { - if (mkdirat (AT_FDCWD, subdirs[i].path, subdirs[i].mode) < 0) - err (EXIT_FAILURE, "Failed to create dir %s", subdirs[i].path); - } - - g_autofree char *ovl_options - = g_strdup_printf ("lowerdir=%s,upperdir=%s,workdir=%s", lowerdir, upperdir, workdir); - if (mount ("overlay", tmp_sysroot_etc, "overlay", MS_SILENT, ovl_options) < 0) - err (EXIT_FAILURE, "failed to mount transient etc overlayfs"); - } - else - { - /* Bind-mount /etc (at deploy path), and remount as writable. */ - if (mount ("etc", tmp_sysroot_etc, NULL, MS_BIND | MS_SILENT, NULL) < 0) - err (EXIT_FAILURE, "failed to prepare /etc bind-mount at /sysroot.tmp/etc"); - if (mount (tmp_sysroot_etc, tmp_sysroot_etc, NULL, MS_BIND | MS_REMOUNT | MS_SILENT, NULL) - < 0) - err (EXIT_FAILURE, "failed to make writable /etc bind-mount at /sysroot.tmp/etc"); - } + if (!otcore_mount_etc (config, &metadata_builder, TMP_SYSROOT, &error)) + errx (EXIT_FAILURE, "Failed to mount etc: %s", error->message); } /* Prepare /usr.